#include <thread>
#include "erpc/erpc.h"
#include "spd_logger.hpp"
#include "simpost_component.hpp"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>

class sender: public simpost::Component
{
public:
    explicit sender() : Component("sender", "V1.0.0") {}
    virtual ~sender() = default;
    bool init(void) override final;
    void exit(void) override final;
private:
    void app_task(void);
    bool socket_init(const std::string &addr, uint16_t port);
    static void udp_sender(const uint8_t *data, size_t length);
private:
    static int m_sockfd;
    static sockaddr_in m_addr;
};

int sender::m_sockfd = -1;
sockaddr_in sender::m_addr;

bool sender::init(void)
{
    LOG_INFO("sender init");
    if(false == socket_init("127.0.0.1", 10089))
        return false;
    erpc::erpc_sender_register("communicate", udp_sender);
    std::thread app_thread([this]{ app_task(); });
    app_thread.detach();
    return true;
}

void sender::exit(void)
{
    LOG_INFO("sender exit");
}

void sender::app_task(void)
{
    google::protobuf::Any args;
    while (true)
    {
        std::this_thread::sleep_for(std::chrono::seconds(2));
        LOG_INFO("sender report message");
        erpc::erpc_report_publish("communicate", 123, 456, args);
    }
}

bool sender::socket_init(const std::string &addr, uint16_t port)
{
    m_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(m_sockfd < 0)
    {
        LOG_ERROR("create udp socket failed!");
        return false;
    }
    bzero(&m_addr, sizeof(m_addr));
    m_addr.sin_family = AF_INET;
    m_addr.sin_port = htons(port);
    m_addr.sin_addr.s_addr = inet_addr(addr.c_str());
    return true;
}

void sender::udp_sender(const uint8_t *data, size_t length)
{
    sendto(m_sockfd, data, length, 0, (struct sockaddr *)&m_addr, sizeof(struct sockaddr_in));
}

COMPONENT_REGISTER(sender);